package com.tang.util;

import com.tang.domain.Constants;
import com.tang.domain.FileSliceData;
import com.tang.domain.FileSliceInstruct;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * 文件读写工具
 *
 * @author fuzhengwei
 * @since 2019
 */
public class FileUtil {

    /**
     * 读取特定长度的文件分片
     *
     * @param fileUrl      文件url
     * @param readPosition 文件指针偏移
     * @return 文件分片数据
     * @throws IOException IO异常
     */
    public static FileSliceData readFile(String fileUrl, Integer readPosition) throws IOException {
        File file = new File(fileUrl);
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r"); // r: 只读模式 rw:读写模式 "rws", or "rwd"
        /*
            seek(long pos) Sets the file-pointer offset, measured from the beginning of this file, at which the next read or write occurs.
            seek(long pos) 设置文件的起始指针，读或写会从该指针开始
         */
        randomAccessFile.seek(readPosition); // 所以这里就是设置文件指针
        byte[] bytes = new byte[1024 * 100]; // 定义一个byte数组
        /*
            read(byte[] b)  Reads up to b.length bytes of data from this file into an array of bytes.
            read(byte[] b)  从文件中读取至多数组B长度的数据放入字节数组B中
         */
        int readSize = randomAccessFile.read(bytes);
        if (readSize <= 0) { // 如果没读到数据，直接返回咯
            randomAccessFile.close();
            return new FileSliceData(Constants.FileStatus.COMPLETE);//Constants.FileStatus ｛0开始、1中间、2结尾、3完成｝
        }
        FileSliceData fileInfo = new FileSliceData();
        fileInfo.setFileUrl(fileUrl); // 文件地址
        fileInfo.setFileName(file.getName()); // 文件名称
        fileInfo.setBeginPos(readPosition); // 读取的起始指针
        fileInfo.setEndPos(readPosition + readSize); // 读取的结束指针
        // 不足1024需要拷贝去掉空字节
        // 设置文件字节数据
        if (readSize < 1024 * 100) {
            byte[] copy = new byte[readSize];
            System.arraycopy(bytes, 0, copy, 0, readSize);
            fileInfo.setBytes(copy);
            fileInfo.setStatus(Constants.FileStatus.END);
        } else {
            fileInfo.setBytes(bytes);
            fileInfo.setStatus(Constants.FileStatus.CENTER);
        }
        randomAccessFile.close();
        return fileInfo;
    }

    /**
     * 根据分片数据分片的写入文件
     *
     * @param baseUrl       写入的URL
     * @param fileBurstData 文件分片数据
     * @return 写入数据
     * @throws IOException IO异常
     */
    public static FileSliceInstruct writeFile(String baseUrl, FileSliceData fileBurstData) throws IOException {
        // 判断是否是结束的
        if (Constants.FileStatus.COMPLETE == fileBurstData.getStatus()) {
            return new FileSliceInstruct(Constants.FileStatus.COMPLETE); //Constants.FileStatus ｛0开始、1中间、2结尾、3完成｝
        }

        File file = new File(baseUrl + "/" + fileBurstData.getFileName());
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");//r: 只读模式 rw:读写模式 "rws", or "rwd"
        randomAccessFile.seek(fileBurstData.getBeginPos());      // 移动文件记录指针的位置,
        /*
            write(byte[] b) Writes b.length bytes from the specified byte array to this file, starting at the current file pointer.
            write(byte[] b) 从指针开始将字节数组b的数据写入文件
         */
        randomAccessFile.write(fileBurstData.getBytes());
        randomAccessFile.close();

        if (Constants.FileStatus.END == fileBurstData.getStatus()) {
            return new FileSliceInstruct(Constants.FileStatus.COMPLETE); //Constants.FileStatus ｛0开始、1中间、2结尾、3完成｝
        }

        //文件分片传输指令
        FileSliceInstruct fileBurstInstruct = new FileSliceInstruct();
        fileBurstInstruct.setStatus(Constants.FileStatus.CENTER);            //Constants.FileStatus ｛0开始、1中间、2结尾、3完成｝
        fileBurstInstruct.setClientFileUrl(fileBurstData.getFileUrl());      //客户端文件URL
        fileBurstInstruct.setReadPosition(fileBurstData.getEndPos() + 1);    //读取位置

        return fileBurstInstruct;
    }

}
